/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     vogella GmbH - Bug 287303 - [patch] Add Word Wrap action to Console View
 *     Paul Pazderski  - Bug 550621 - improved verification of user input
 *******************************************************************************/
package cn.bbstone.e4.ui.log.views;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.e4.ui.di.UISynchronize;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IScrollLockStateProvider;
import org.eclipse.ui.console.TextConsole;
import org.eclipse.ui.internal.console.IOConsoleViewer;

import cn.bbstone.e4.ui.log.job.E4WorkbenchJob;

/**
 * 
 * and will change other part for E4 used.
 * 
 * Viewer used to display an {@link IOConsole}.
 *
 * @since 3.1
 * @see org.eclipse.ui.internal.console.IOConsoleViewer
 * 
 * 
 *      NOTICE: this source file is copy from
 *      {@link org.eclipse.ui.internal.console.IOConsoleViewer}, and adapted to
 *      match E4 application model.
 * 
 *      replace revealJob implementation in TextConsoleViewer(E3) with
 *      E4WorkbenchJob( extends E4UIJob) for autoScroll function, can referTo
 *      TrimJob in this class
 * 
 * 
 * 
 * 
 */
@SuppressWarnings("restriction")
public class LogsIOConsoleViewer extends IOConsoleViewer {

	private UISynchronize sync;

	/**
	 * Listener required for auto scroll.
	 */
	private IDocumentListener fAutoScrollListener;
	
	private E4WorkbenchJob revealJobx;

	/**
	 * Constructs a new viewer in the given parent for the specified console.
	 *
	 * @param parent  the containing composite
	 * @param console the IO console
	 */
	public LogsIOConsoleViewer(Composite parent, TextConsole console, UISynchronize sync) {
		super(parent, console);
		this.sync = sync;

		initAutoScroll(console);
	}

	public LogsIOConsoleViewer(Composite parent, LogsIOConsole console, UISynchronize sync) {
		super(parent, console);
		this.sync = sync;

		initAutoScroll(console);
	}

	private void initAutoScroll(TextConsole console) {
		IDocument document = console.getDocument();

		revealJobx = new AutoScrollJob(sync);
		revealJobx.setRule(console.getSchedulingRule());
		revealJobx.setSystem(true);

		if (document != null) {
			document.addDocumentListener(getAutoScrollListener());
		}
	}

	/**
	 * Constructs a new viewer in the given parent for the specified console.
	 *
	 * @param parent                  the containing composite
	 * @param console                 the IO console
	 * @param scrollLockStateProvider the scroll lock state provider
	 * @since 3.6
	 */
	public LogsIOConsoleViewer(Composite parent, TextConsole console,
			IScrollLockStateProvider scrollLockStateProvider) {
		super(parent, console, scrollLockStateProvider);
	}

	@Override
	public boolean isAutoScroll() {
		return super.isAutoScroll();
	}

	@Override
	public void setAutoScroll(boolean scroll) {
		super.setAutoScroll(scroll);
	}

	@Override
	public boolean isWordWrap() {
		return super.isWordWrap();
	}

	@Override
	public void setWordWrap(boolean wordwrap) {
		super.setWordWrap(wordwrap);
	}

	@Override
	public void setReadOnly() {
		super.setReadOnly();
	}

	@Override
	public boolean isReadOnly() {
		return super.isReadOnly();
	}

	/**
	 * Job to trim the console document, runs in the UI thread.
	 */
	private class AutoScrollJob extends E4WorkbenchJob {

		/**
		 * Creates a new job for auto scrolling
		 */
		AutoScrollJob(UISynchronize sync) {
			super(sync, "Auto Scroll Job"); //$NON-NLS-1$
//			setSystem(true);
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			scrollToEndOfDocument();
			return Status.OK_STATUS;
		}

	}

//	E4WorkbenchJob revealJobx = new AutoScrollJob(sync);
//	E4WorkbenchJob(sync, "Reveal End of Document") {
//		@Override
//		public IStatus runInUIThread(IProgressMonitor monitor) {
//			scrollToEndOfDocument();
//			return Status.OK_STATUS;
//		}
//	};

	// reveal the end of the document
	private void scrollToEndOfDocument() {
		StyledText textWidget = getTextWidget();
		if (textWidget != null && !textWidget.isDisposed()) {
			int lineCount = textWidget.getLineCount();
			textWidget.setTopIndex(lineCount > 0 ? lineCount - 1 : 0);
		}

	}

	protected void revealEndOfDocument() {
		revealJobx.schedule();
	}

	private IDocumentListener getAutoScrollListener() {
		if (fAutoScrollListener == null) {
			fAutoScrollListener = new IDocumentListener() {
				@Override
				public void documentAboutToBeChanged(DocumentEvent event) {
				}

				@Override
				public void documentChanged(DocumentEvent event) {
					if (isAutoScroll()) {
						revealEndOfDocument();
					}
				}
			};
		}
		return fAutoScrollListener;
	}
	
	public void dispose() {
		revealJobx.cancel();
	}

}
